#include <iostream>
#include <vector>
#include <memory>
#include <string>

// 访问者接口
class Visitor {
public:
    virtual ~Visitor() = default;
    virtual void visitBook(const class Book& book) = 0;
    virtual void visitMovie(const class Movie& movie) = 0;
};

// 元素接口
class Element {
public:
    virtual ~Element() = default;
    virtual void accept(Visitor& visitor) const = 0;
};

// 具体元素：书籍
class Book : public Element {
private:
    std::string title;
    double price;

public:
    Book(const std::string& t, double p) : title(t), price(p) {}

    const std::string& getTitle() const { return title; }
    double getPrice() const { return price; }

    void accept(Visitor& visitor) const override {
        visitor.visitBook(*this);
    }
};

// 具体元素：电影
class Movie : public Element {
private:
    std::string title;
    double price;

public:
    Movie(const std::string& t, double p) : title(t), price(p) {}

    const std::string& getTitle() const { return title; }
    double getPrice() const { return price; }

    void accept(Visitor& visitor) const override {
        visitor.visitMovie(*this);
    }
};

// 具体访问者：计算总价格
class PriceCalculator : public Visitor {
private:
    double totalPrice = 0.0;

public:
    void visitBook(const Book& book) override {
        totalPrice += book.getPrice();
    }

    void visitMovie(const Movie& movie) override {
        totalPrice += movie.getPrice();
    }

    double getTotalPrice() const {
        return totalPrice;
    }
};

// 具体访问者：显示信息
class InfoDisplay : public Visitor {
public:
    void visitBook(const Book& book) override {
        std::cout << "Book: " << book.getTitle() << ", Price: $" << book.getPrice() << "\n";
    }

    void visitMovie(const Movie& movie) override {
        std::cout << "Movie: " << movie.getTitle() << ", Price: $" << movie.getPrice() << "\n";
    }
};

// 对象结构
class ObjectStructure {
private:
    std::vector<std::shared_ptr<Element>> elements;

public:
    void addElement(const std::shared_ptr<Element>& element) {
            elements.push_back(element);
    }

    void accept(Visitor& visitor) const {
        for (const auto& element : elements) {
                    element->accept(visitor);
        }
    }
};

// 客户端代码
int main() {
    // 创建对象结构
    ObjectStructure structure;
    structure.addElement(std::make_shared<Book>("C++ Programming", 50.0));
    structure.addElement(std::make_shared<Movie>("Inception", 20.0));
    structure.addElement(std::make_shared<Book>("Design Patterns", 70.0));

    // 使用价格计算访问者
    PriceCalculator priceCalculator;
    structure.accept(priceCalculator);
    std::cout << "Total Price: $" << priceCalculator.getTotalPrice() << "\n";

    // 使用信息显示访问者
    InfoDisplay infoDisplay;
    structure.accept(infoDisplay);

    return 0;
}